package com.atguigu.gmall.product.service.impl;

import com.atguigu.gmall.product.service.TestService;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class TestServiceImpl implements TestService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;


    @Override
    public void testLock() {
         /*
        1.  缓存中设置一个key  num = 0
        2.  从缓存中获取这个数据
                true:
                    对num+1 在放入缓存.
                false:
                    return;
         */
        //  上锁：参数锁的名称：
        RLock lock = redissonClient.getLock("lock");
        //  lock.lock();
        lock.lock();
        //  业务逻辑代码：
        //  获取数据：  get num
        String num = redisTemplate.opsForValue().get("num");
        //  判断
        if (StringUtils.isEmpty(num)){
            return;
        }
        //  对num+1;  int i = 1/0;
        int numValue = Integer.parseInt(num);
        //  写入缓存. set key value;
        this.redisTemplate.opsForValue().set("num",String.valueOf(++numValue));
        //  解锁：
        lock.unlock();

    }

    @Override
    public String readLock() {
        //  声明锁对象
        RReadWriteLock rwlock = redissonClient.getReadWriteLock("anyRWLock");
        //  上锁
        rwlock.readLock().lock(10,TimeUnit.SECONDS);
        //  从缓存中读取数据
        String msg = this.redisTemplate.opsForValue().get("msg");

        //  为了测试读写锁效果不删除！
        return msg;
    }

    @Override
    public String writeLock() {
        //  声明锁对象
        RReadWriteLock rwlock = redissonClient.getReadWriteLock("anyRWLock");
        //  上锁
        rwlock.writeLock().lock(10,TimeUnit.SECONDS);
        String s = UUID.randomUUID().toString();
        this.redisTemplate.opsForValue().set("msg",s);
        //  为了测试读写锁效果不删除！
        return s;
    }
    /*
    1.  缓存中设置一个key  num = 0
    2.  从缓存中获取这个数据
            true:
                对num+1 在放入缓存.
            false:
                return;
     */
//    @Override
//    public void testLock() {
//        //  设置一个uuid
//        String uuid = UUID.randomUUID().toString();
//        //  判断是否有锁存在！ setnx key value;
//        //  Boolean result = this.redisTemplate.opsForValue().setIfAbsent("lock", "ok");
//        //  set key value ex 3 nx;
//        Boolean result = this.redisTemplate.opsForValue().setIfAbsent("lock", uuid,3, TimeUnit.SECONDS);
//            if (result){
//                //  result = true; 上锁成功，里面没人执行业务.
//                //  获取数据：  get num
//                String num = redisTemplate.opsForValue().get("num");
//                //  判断
//                if (StringUtils.isEmpty(num)){
//                    return;
//                }
//                //  对num+1;  int i = 1/0;
//                int numValue = Integer.parseInt(num);
//                //  写入缓存. set key value;
//                this.redisTemplate.opsForValue().set("num",String.valueOf(++numValue));
//                //  声明一个lua脚本：
//                String scriptText = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
//                        "then\n" +
//                        "    return redis.call(\"del\",KEYS[1])\n" +
//                        "else\n" +
//                        "    return 0\n" +
//                        "end";
//                //  判断当前是否可以删除锁.
//                //                if (uuid.equals(this.redisTemplate.opsForValue().get("lock"))){
//                //                    //  释放锁：小明要删除锁！突然cpu 让出执行权限,锁刚好过期！ 小丽进来：redis-uuid = 小丽； cpu 将执行权限交给了小明：删除的是小丽的锁！
//                //                    this.redisTemplate.delete("lock");
//                //                }
//                DefaultRedisScript<Long> defaultRedisScript = new DefaultRedisScript<>();
//                defaultRedisScript.setScriptText(scriptText);
//                defaultRedisScript.setResultType(Long.class);
//                //  RedisScript: key的集合 value；
//                this.redisTemplate.execute(defaultRedisScript, Arrays.asList("lock"),uuid);
//
//            } else {
//              //    等待自旋;
//                try {
//                    Thread.sleep(200);
//                } catch (InterruptedException e) {
//                    throw new RuntimeException(e);
//                }
//                testLock();
//            }
//    }
    // 第一个案例
//    @Override
//    public synchronized void testLock() {
//        //  获取数据：  get num
//        String num = redisTemplate.opsForValue().get("num");
//        //  判断
//        if (StringUtils.isEmpty(num)){
//            return;
//        }
//        //  对num+1;
//        int numValue = Integer.parseInt(num);
//        //  写入缓存. set key value;
//        this.redisTemplate.opsForValue().set("num",String.valueOf(++numValue));
//    }
}
